package com.iflytek.uc.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.exception.SQLGrammarException;
import org.hibernate.impl.SessionImpl;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

import com.iflytek.uc.service.InitializationService;

public class InitializationServiceImpl implements InitializationService {

	private static final Logger LOG = Logger.getLogger(InitializationServiceImpl.class);
	
	private SessionFactory sessionFactory;
	private String sqlScriptPath;
	private String delimeter = ";";
	private String encoding = "utf-8";
	private String validationQuery;

	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public void setSqlScriptPath(String sqlScriptPath) {
		this.sqlScriptPath = sqlScriptPath;
	}

	public void setDelimeter(String delimeter) {
		this.delimeter = delimeter;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}

	public void setValidationQuery(String validationQuery) {
		this.validationQuery = validationQuery;
	}

	public void initialize() {
		LOG.info("create tables if not exist");
		boolean existed = false;
		try {
			Query query = sessionFactory.openSession().createQuery(validationQuery);
			query.uniqueResult();
			
			existed = true;
		}
		catch (SQLGrammarException e) {
			//do nothind
		}
		
		if (!existed) {
			createSchemaAndLogic();
		}
	}
	
	private void createSchemaAndLogic() {
		LOG.info("create tables for user center");

		String dbType = getDbType();
		
		String schemaScript = getSchemaScript(dbType);
		String logicScript = getLogicScript();
		
		executeScript(schemaScript);
		executeScript(logicScript);
	}
	
	private void executeScript(String scriptFile) {
		Resource res = null;
		if (scriptFile.startsWith("classpath:")) {
			String path = scriptFile.substring("classpath:".length());
			res = new ClassPathResource(path);
		}
		else {
			res = new FileSystemResource(scriptFile);
		}
		
		InputStream is = null;
		try {
			is = res.getInputStream();
			List<String> lines = IOUtils.readLines(is, encoding);
			StringBuilder s = getContent(lines);
			String[] sqls = s.toString().split(delimeter);
			
			Session session = sessionFactory.openSession(); 
			for (String sql : sqls) {
				if (!StringUtils.isBlank(sql)) {
					Query query = session.createSQLQuery(sql);
					query.executeUpdate();
				}
			}
		} 
		catch (IOException e) {
			LOG.error("", e);
		}
		finally {
			try {is.close(); } catch (Exception e) {}
		}
	}
	
	private StringBuilder getContent(List<String> lines) {
		StringBuilder s = new StringBuilder("");
		for (String line : lines) {
			s.append(line).append("\r\n");
		}
		return s;
	}

	private String getDbType() {
		String dialect = ((SessionImpl)sessionFactory.openSession()).getFactory().getDialect().getClass().getName();
		dialect = dialect.toLowerCase();
		String dbType = null;
		if (dialect.indexOf("oracle") >= 0) {
			dbType = "oracle";
		}
		else if (dialect.indexOf("h2") >= 0) {
			dbType = "h2";
		}
		else if (dialect.indexOf("mysql") >= 0) {
			dbType = "mysql";
		}
		else {
			dbType = dialect;
		}
		return dbType;
	}
	
	private String getSchemaScript(String dbType) {
		return sqlScriptPath + "/" + dbType + ".sql";
	}
	
	private String getLogicScript() {
		return sqlScriptPath + "/data.sql";
	}
}
